(function($) { $(“body”).on(“click”, “.mybutton”, function(event) { alert(“Button clicked”); }; })($)
JavaScript has become more and more popular over the last few years, without any doubts its usage will continue to increase. GateIn is an aggregation platform focusing on aggregating markup in the browser with portlets, but also on integrating JavaScript in the same browser: each application comes with markup and JavaScript, more and more JavaScript. GateIn JavaScript integration until version 3.2 was designed a long time ago and was not able to answer the most recent needs required by modern web applications.
Since version 3.3, we started an effort to bring GateIn to support the most recent use cases of JavaScript integration. GateIn 3.3 and 3.4 are transitional versions that improved JavaScript support but were not able to answer all the use case we had in mind. GateIn 3.5 finally met the goals and reached maturity. Performance is the most important concern, GateIn provides now on demand, flexible and parallel loading of JavaScript resources. Support for modularity is fully addressed, it allows to integrate better JavaScript by providing a natural isolation mechanism between applications. Last but not least, GateIn internal JavaScript was rewritten on top of the jQuery library running in total isolation of the portlet runtimes, while it may seem an implementation detail, it deserves to be mentioned.
GateIn JavaScript improvements is built on top of the notion of JavaScript module. JavaScript does not provide a natural way for namespacing, the notion of module was designed to solve this problem. This natural lack of namespacing can be perceived as a lack, instead it should be seen as an advantage as modules provide namespacing and more: indeed the module pattern allows to create dependencies between modules and resolve them at runtime enabling on demand and parallel loading of JavaScript resources.
This guide will not explain modules because we haven’t designed a module system for GateIn. Instead GateIn uses the RequireJS library and integrates. Therefore the best documentation you can read about modules is the RequireJS documentation you can also read the excellent article written by Ben Cherry about modules in depth.
Ecmascript 6 will provide native modules, you can read more about in this article
In the essence the notion of module can be viewed as:
An identifier or name
A list of dependencies on the modules required by the module to work properly
The code packaged usually expressed as a self-executing function
The product which is an object produced by the module that is usually consumed by other modules
At runtime the dependency system defines a graph of function to execute, the product of each module being injected in the other modules. It can be seen as a simple dependency injection system able to load modules in an asynchronous and parallel fashion providing parallel loading, namespacing and dependency management.
GateIn 3.5 provides support for different module format:
GateIn Module Definition (GMD): the most appropriate way to define a JavaScript module in GateIn. The module is expressed as a simple function, the list of dependencies being expressed in the gatein-resources.xml file. This format clearly decouples the module code in a JavaScript file from the module dependencies expressed in a single XML file and is the best trade off for integrating JavaScript in GateIn.
Asynchronous Module Definition (AMD): the native module format supported by RequireJS.
Adapted Module: this format is the most flexible one as it allows to adapt to other module format such as CommonJS modules.
Previously we said that modules provide more than just namespacing, this section explains the other benefits of modules. Let’s write a module consuming the jQuery library:
(function($) { $(“body”).on(“click”, “.mybutton”, function(event) { alert(“Button clicked”); }; })($)
The JavaScript side of our module is a mere function that takes as argument the jQuery $ object:
The jQuery object is provided as a module dependency expressed as a function argument $. The module code can use the name it likes for jQuery, in our module we use the $ name
$ jQuery can be used without needing to tuse the $.ready function because jQuery will be already loaded and initialized when the function is executed
The module is scoped to the entire page and this code will react to any click on the .mybutton selector. Since a single event listener handles as many portlets as we have on the page we benefit of performance but also simplicity
Let’s now integrate this module in GateIn, for this matter we declare it in the gatein-resources.xml file of the war file:
<gatein-resources xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.gatein.org/xml/ns/gatein_resources_1_3 http://www.gatein.org/xml/ns/gatein_resources_1_3" xmlns="http://www.gatein.org/xml/ns/gatein_resources_1_3"> <portlet> <name>MyPortlet</name> <module> <script> <path>/mymodule.js</path> </script> <depends> <module>jquery</module> <as>$</as> </depends> </module> </portlet> </<gatein-resources>
The module tag declares our module and its dependencies, in this case we declare that jQuery is the only dependency and it should be named $ when our module is executed. We have created a dependency relationship between our module and the jQuery module:
Our module will be loaded only when the portlet is displayed
GateIn will first load the jQuery module before loading our module
Several different versions of jQuery can coexist in the browser without conflicting
This introductory example is simple but outlines the important features provided by modules: performance, isolation, dependency management and ease of use.
Modules should be used when possible but it is not always possible, for example when an existing portlet uses an inline script it will access the global namespace to find functions or objects. Although it is advocated to use modules, GateIn 3.5 provides supports this traditional way of using JavaScript with a simple script declaration in the head section of a web page. Dependencies between such script can be created to order the scripts in the head section and resolve dependency problems as much as possible.